package Core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Vector;

import sun.security.provider.certpath.AdjacencyList;

import com.sun.xml.internal.messaging.saaj.packaging.mime.util.QDecoderStream;

public class Graph {

	static int NO_OF_INITIAL_VERTICES = 10;

	static int V = NO_OF_INITIAL_VERTICES;

	static GraphGenerator graphGenerator = new GraphGenerator(V, 0.60, 2, 1,
			70, 30);

	private static double THRESHOLD_VALUE = 0.3;

	static Vector<Integer> weightA = new Vector<Integer>();
	static Vector<Integer> weightB = new Vector<Integer>();

	public static void main(String args[]) throws IOException {

		System.out.println("Threshold value is " + THRESHOLD_VALUE);
		System.out.println("Density is " + graphGenerator.density);
		System.out.println("p_A is " + graphGenerator.p_A);
		System.out.println("p_B is " + graphGenerator.p_B);
		System.out.println("ratioA is " + graphGenerator.ratioA);
		System.out.println("ratioB is " + graphGenerator.ratioB);
		System.out.println("For topic A :-");

		int NO_OF_RUNS = 3;

		int size = 10 + 5 * (NO_OF_RUNS - 1);
		
		double totalA[] = new double[NO_OF_RUNS];
		double totalB[] = new double[NO_OF_RUNS];
		
		for(int i = 0; i < NO_OF_RUNS; i ++) {
			totalA[i] = 0;
			totalB[i] = 0;
		}

		double[][] networkA = new double[NO_OF_RUNS][size];
		double[][] networkB = new double[NO_OF_RUNS][size];

		for (int y = 0; y < NO_OF_RUNS; y++) {

			// System.out.println("Run " + (y + 1) + ":\n");

			if (y != 0) {
				graphGenerator.increaseSize(5);
				V += 5;
			}

			// double networkA[] = new double[V];
			// double networkB[] = new double[V];

			Vector<Vector<IntegerPair>> AdjList = new Vector<Vector<IntegerPair>>();
			Vector<Vector<IntegerPair>> AdjListB = new Vector<Vector<IntegerPair>>();

			AdjList = graphGenerator.getListA();
			AdjListB = graphGenerator.getListB();

			/*
			 * for(int i = 0; i < V; i ++) { for(int j = 0; j <
			 * AdjList.get(i).size(); j ++) {
			 * System.out.print(AdjList.get(i).get(j).first() + " " +
			 * AdjList.get(i).get(j).second() + "\t"); } System.out.println(); }
			 */

			/*
			 * for(int i = 0; i < V; i ++) { for(int j = 0; j <
			 * AdjListB.get(i).size(); j ++) {
			 * System.out.print(AdjListB.get(i).get(j).first() + " " +
			 * AdjListB.get(i).get(j).second() + "\t"); } System.out.println();
			 * }
			 */

			weightA = graphGenerator.getICA();
			weightB = graphGenerator.getICB();

			for (int z = 0; z < V; z++) {

				LinkedList<IntegerPair> q = new LinkedList<IntegerPair>();
				LinkedList<IntegerPair> qB = new LinkedList<IntegerPair>();

				double minB[] = new double[V];
				double minBB[] = new double[V];

				for (int i = 0; i < V; i++) {
					minB[i] = 0.0;
					minBB[i] = 0.0;
				}

				minB[z] = 1;
				minBB[z] = 1;

				IntegerPair start = new IntegerPair(z, 1.0);
				IntegerPair startB = new IntegerPair(z, 1.0);

				q.add(start);
				qB.add(startB);

				while (!q.isEmpty()) {
					// System.out.println("I am here");
					IntegerPair current = q.poll();
					int vertexCurrent = current.first();
					double weight = minB[vertexCurrent];
					for (int j = 0; j < AdjList.get(vertexCurrent).size(); j++) {
						// System.out.println("I reach the inner loop");
						IntegerPair vertex = AdjList.get(vertexCurrent).get(j);
						double newWeight = weight * vertex.second() / 2;
						if (newWeight <= 0.1) {
							// System.out.println("I reach threshold");
							break;
						}
						if (minB[vertex.first()] < newWeight) {
							minB[vertex.first()] = newWeight;
							q.add(vertex);
						}
					}
				}

				/*
				 * for(int i = 0; i < V; i ++) { System.out.print(minB[i] +
				 * "\t"); }
				 */
				// System.out.println();

				while (!qB.isEmpty()) {
					IntegerPair current = qB.poll();
					int vertexCurrent = current.first();
					double weight = minBB[vertexCurrent];
					for (int j = 0; j < AdjListB.get(vertexCurrent).size(); j++) {
						IntegerPair vertex = AdjListB.get(vertexCurrent).get(j);
						double newWeight = weight * vertex.second() / 2;
						if (newWeight <= 0.1)
							break;
						if (minBB[vertex.first()] < newWeight) {
							minBB[vertex.first()] = newWeight;
							qB.add(vertex);
						}
					}
				}

				double sumA = 0;
				double sumB = 0;

				for (int i = 0; i < V; i++) {
					sumA = sumA + weightA.get(i) * minB[i];
					sumB = sumB + weightB.get(i) * minBB[i];
				}

				networkA[y][z] = sumA;
				networkB[y][z] = sumB;

				// System.out.println("Weight related to A of network of vertex "
				// + z + " is " + networkA[z]);
				// System.out.println("Weight related to B of network of vertex "
				// + z + " is " + networkB[z]);

			}

			for (int i = 0; i < V; i++) {
				totalA[y] += networkA[y][i];
				totalB[y] += networkB[y][i];
			}

		}

		System.out.print("\t");
		for(int i = 0; i < NO_OF_RUNS; i ++) {
			System.out.print("Run " + (i + 1) + "\t\t\t\t");
		}
		System.out.println();
		
		for (int i = 0; i < V; i++) {
			System.out.print(i + "\t");
			for(int j = 0; j < NO_OF_RUNS; j ++) {
				System.out.print(networkA[j][i]/totalA[j] + "\t\t");
				if(networkA[j][i] == 0.0) {
					System.out.print("\t\t");
				}
			}
			System.out.println();
		}
		
		
		System.out.println("For topic B :-");
		System.out.print("\t");
		for(int i = 0; i < NO_OF_RUNS; i ++) {
			System.out.print("Run " + (i + 1) + "\t\t\t\t");
		}
		System.out.println();
		
		for (int i = 0; i < V; i++) {
			System.out.print(i + "\t");
			for(int j = 0; j < NO_OF_RUNS; j ++) {
				System.out.print(networkB[j][i]/totalB[j] + "\t\t");
				if(networkB[j][i] == 0.0) {
					System.out.print("\t\t");
				}
			}
			System.out.println();
		}
	}
}